package cn.tedu.charging.cost.service;

import cn.tedu.charging.common.pojo.param.ProgressCostParam;
import cn.tedu.charging.common.pojo.po.ChargingCostRulePO;
import cn.tedu.charging.common.pojo.vo.ProgressCostVO;
import cn.tedu.charging.cost.repository.CostRuleRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;

@Service
@Slf4j
public class CostServiceImpl implements CostService{
    @Autowired
    private CostRuleRepository costRuleRepository;
    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public ProgressCostVO calculateCost(ProgressCostParam param) {
        /*
            1. 利用参数中 stationId 和gunId 获取枪类型 计算当前系统时间所属的时间段
            上午尖 [8~12)点 下午尖 [14~18)
            峰 [18~24)
            平 [12~14)
            谷 [0~8)
            select * from charging_cost_rule where station_id=5 and start_time<=now()
            and end_time>now()
         */
        ChargingCostRulePO rule=getCostRule(5,new Date());
        if(rule==null){
            log.error("没有找到对应的计价规则");
        }
        log.info("当前计价规则 命中的时间段:{}",rule.getName());
        //2.入参电度数 规则单价 计算本次金额
        BigDecimal onceFee=calculateOnceFee(param.getChargingCapacity(),rule.getPowerFee());
        //3.时间和 金额累加
        Long totalTime=accumulateTime(20L,param.getOrderNo());//默认一次充电时间20秒
        BigDecimal totalFee=accumulateFee(onceFee,param.getOrderNo());
        //4.封装VO返回
        ProgressCostVO vo=new ProgressCostVO();
        vo.setTotalCost(totalFee.doubleValue());
        vo.setPowerFee(rule.getPowerFee().doubleValue());
        vo.setTotalTime(totalTime);
        return vo;
    }

    private BigDecimal accumulateFee(BigDecimal onceFee,String billId) {
        String feeKey="charging:bill:fee:"+billId;
        //金额是浮点型,redisTemplate自动识别 转化了浮点型和整形过程
        Double increment = redisTemplate.opsForValue().increment(feeKey, onceFee.doubleValue());
        return new BigDecimal(increment).setScale(2, RoundingMode.HALF_UP);
    }

    private Long accumulateTime(Long time,String billId) {
        String timeKey="charging:bill:time:"+billId;
        Long increment = redisTemplate.opsForValue().increment(timeKey, time);
        return increment;
    }

    private BigDecimal calculateOnceFee(Double capacity, BigDecimal powerFee) {
        //充电度数capacity*单价powerFee
        //BigDecimal + plus - minus - multiply / devided
        //精度2为 四舍五入
        BigDecimal onceFee=powerFee.multiply(new BigDecimal(capacity)).setScale(2, RoundingMode.HALF_UP);
        return onceFee;
    }

    private ChargingCostRulePO getCostRule(Integer stationId, Date date) {
        return costRuleRepository.getCostRule(stationId,date.getHours());
    }
}
